<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h3 data-lake-id="JYFyq" id="JYFyq"><span data-lake-id="uee49ddd5" id="uee49ddd5">背景</span></h3>
  <p data-lake-id="ufad3243c" id="ufad3243c"><span data-lake-id="uee41114c" id="uee41114c"><br>
    我的项目中，有这样一个场景，我们要发起一个用户主动还款之后，需要把在途的扣款单全部暂停，但是因为用户选择还款单据可能比较多，而且暂停是调用外部资金打款系统的接口实现的，这个地方如果一条一条执行就很慢，但是如果起多线程执行的话，我就没办法知道他们每一个暂定的返回结果。</span></p>
  <p data-lake-id="u71a2d68c" id="u71a2d68c"><span data-lake-id="ua9f59e6e" id="ua9f59e6e">​</span><br></p>
  <p data-lake-id="uf5b808f4" id="uf5b808f4"><span data-lake-id="u4df5a04c" id="u4df5a04c">我想可以实现一个这样的功能：多线程去执行暂停动作，如果都成功了，那么就推进我的主动扣款后续流程，如果暂停有任何一个接口调用失败了，那么先不推进后续流程，等下次重试。</span></p>
  <h3 data-lake-id="UWcPL" id="UWcPL"><span data-lake-id="u9044811a" id="u9044811a"><br></span><span data-lake-id="u2e235323" id="u2e235323">技术选型</span></h3>
  <p data-lake-id="u794f9f16" id="u794f9f16"><span data-lake-id="u1c9216f3" id="u1c9216f3">​</span><br></p>
  <p data-lake-id="ue9f4b304" id="ue9f4b304"><span data-lake-id="u1257da4a" id="u1257da4a">为了实现这个功能，我了解到CompletableFuture，他是Java 8中引入的一个新特性，它提供了一种简单的方法来实现异步编程和任务组合。</span></p>
  <p data-lake-id="u73b4eb46" id="u73b4eb46"><span data-lake-id="u4bb3f561" id="u4bb3f561">​</span><br></p>
  <p data-lake-id="ua839a7b1" id="ua839a7b1"><span data-lake-id="uf7be875b" id="uf7be875b">他的多线程编排的能力刚好可以用在我这个场景中，而且他底层是基于ForkJoinPool实现的，所以他的性能也比较高效，所以最终我选择了这个方案。</span></p>
  <p data-lake-id="udfd3a9c2" id="udfd3a9c2"><br></p>
  <h3 data-lake-id="kubu8" id="kubu8"><span data-lake-id="uc1f5f49c" id="uc1f5f49c">具体实现</span></h3>
  <p data-lake-id="ubce9a5c9" id="ubce9a5c9"><br></p>
  <pre lang="java"><code>
//异步暂停扣款
CompletableFuture&lt;Void&gt; allFutures = CompletableFuture.allOf(noticeDetails.stream()
        .map(detail -&gt; CompletableFuture.supplyAsync(() -&gt; {
            pause(detail);
            return null;
        })).toArray(CompletableFuture[]::new));

//所有暂停扣款成功后，更新代还通知单
allFutures.whenComplete((v, e) -&gt; {
    if (e == null) {
        //执行后续的还款操作
        //...
        //...
    } else {
        log.error("notice failed", e);
    }
});
</code></pre>
  <p data-lake-id="ud634d4fd" id="ud634d4fd"><br></p>
  <h3 data-lake-id="PrjRq" id="PrjRq"><span data-lake-id="u8217e587" id="u8217e587">得到结果</span></h3>
  <p data-lake-id="u7576e6ac" id="u7576e6ac"><br></p>
  <p data-lake-id="u79e67855" id="u79e67855"><span data-lake-id="u13a8dc65" id="u13a8dc65">在用了CompletableFuture做编排之前，原来50笔订单的暂停扣款，需要大概10s左右，但是用了CompletableFuture之后，50笔订单的暂停扣款只需要1秒钟左右。</span></p>
  <p data-lake-id="u9614fc1a" id="u9614fc1a"><span data-lake-id="u2fa31b9d" id="u2fa31b9d">​</span><br></p>
  <h3 data-lake-id="EgNab" id="EgNab"><span data-lake-id="u5d1b21cd" id="u5d1b21cd">学习资料</span></h3>
  <p data-lake-id="u75400c2a" id="u75400c2a"><br></p>
  <p data-lake-id="u77a5c100" id="u77a5c100"><br></p>
  <p data-lake-id="u783e5007" id="u783e5007"><span data-lake-id="u4f7b5103" id="u4f7b5103"><br><br></span></p>
 </body>
</html>